// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module vgpio_espi_wrapper
  #(
    parameter DEVICE_FAMILY              = "MAX 10 FPGA",
    parameter IO_MODE_RANGE              = 2'b11,
    parameter OPEN_DRAIN_ALERT_EN        = 1'b0,
    parameter MAX_FREQ_RANGE             = 3'b000,
    parameter CHANNEL_SUPPORT            = 8'b00000111,
    parameter MAX_PC_PAYLOAD_SIZE_RANGE  = 3'b001,
    parameter MAX_PC_READREQ_SIZE_RANGE  = 3'b001,
    parameter MAX_OOB_PAYLOAD_SIZE_RANGE = 3'b001,
    parameter MAX_VW_COUNT_SUPPORTED     = 6'b000111,
    parameter TABLE_VERSION              = 32'h0000_0000
    )
    (
     input logic          clk,
     input logic          reset_n,
     // eSPI interface
     input logic          spi_clk,
     input logic          spi_reset_n,
     input logic          spi_cs_n,
     input logic [3:0]    spi_data_in,
     output logic [3:0]   spi_data_out,
     output logic         spi_alert_n,
     // Platform registers
     output logic [7:0]   plt_csr0,
     output logic [7:0]   plt_csr1,
     output logic [7:0]   plt_csr2,
     output logic [7:0]   plt_csr3,
     output logic [7:0]   plt_csr4,
     output logic [7:0]   plt_csr5,
     output logic [7:0]   plt_csr6,
     output logic [7:0]   plt_csr7,
     output logic [7:0]   plt_csr8,
     output logic [7:0]   plt_csr9,
     output logic [7:0]   plt_csra,
     output logic [7:0]   plt_csrb,
     output logic [7:0]   plt_csrc,
     output logic [7:0]   plt_csrd,
     output logic [7:0]   plt_csre,
     output logic [7:0]   plt_csrf,
     // VW sys inputs
     input  logic         nmi_n,
     input  logic         smi_n,
     input  logic         oob_rst_ack,
     input  logic         wake_n,
     input  logic         pme_n,
     input  logic         slave_boot_load_done,
     input  logic         error_fatal,
     input  logic         error_nonfatal,
     input  logic         slave_boot_load_status,
     input  logic         sci_n,
     input  logic         host_rst_ack,
     input  logic         rcin_n,
     output logic         oob_rst_warn,
     output logic         host_rst_warn,
     // Used to reset VGPIO inputs
     input  logic         PWRGD_AUX_PWRGD_CPU0_PLD,
     // GPO from master to slave
     output logic         FM_UPI_INIT_DONE,
     output logic         RES_140_2,
     output logic         FM_ADR_MODE0,
     output logic         FM_PERST_DELAY_SEL,
     // GPI from slave to master,
     input  logic         FM_PASSWORD_CLEAR_N,
     input  logic         FM_BOARD_SKU_ID0,
     input  logic         FM_BOARD_SKU_ID1,
     input  logic         FM_BOARD_SKU_ID2,
     input  logic         FM_BOARD_SKU_ID3,
     input  logic         FM_BOARD_SKU_ID4,
     input  logic         FM_BOARD_SKU_ID5,
     input  logic         RES_147_2,
     input  logic         RES_147_3,
     input  logic         FM_BOARD_REV_ID0,
     input  logic         FM_BOARD_REV_ID1,
     input  logic         FM_BOARD_REV_ID2,
     input  logic         FM_RST_PERST_BIT0,
     input  logic         FM_RISER2_WIDTH,
     input  logic         FM_RISER2_MODE,
     input  logic         FM_RISER3_WIDTH,
     input  logic         FM_RISER3_MODE,
     input  logic         FM_CPU0_INTR_PRSNT_N,
     input  logic         FM_CPU1_INTR_PRSNT_N,
     input  logic         FM_CPU0_INTR_ID,
     input  logic         FM_CPU1_INTR_ID,
     input  logic         FM_PCIE_EV_BIF_EN,
     input  logic         H_CPU0_ERR0_LVC1_N,
     input  logic         FM_SFFX4_EXPCARD_IO_B_0,
     // ESPI base
     output logic [31:0]  device_id_reg,
     output logic [31:0]  general_config_reg,
     output logic [31:0]  channel0_config_reg,
     output logic [31:0]  channel1_config_reg,
     output logic [31:0]  channel2_config_reg,
     output logic [31:0]  channel3_config_reg
     );

    logic               slp_s5_n;
    logic               slp_s4_n;
    logic               slp_s3_n;
    logic               slp_a_n;
    logic               slp_lan_n;
    logic               slp_wlan_n;
    logic               sus_stat_n;
    logic               smiout_n;
    logic               nmiout_n;
    
    logic               rsmrst_n;
    logic               pltrst_n;
    logic               sus_warn_n;
    logic               sus_pwrdn_ack;
    logic               host_c10;

     
     logic               vw_channel_en;
     
    // eSPI I/O Read/Write interface
    logic               io_reset;
    logic [15:0]        io_address;
    logic               io_write;
    logic [7:0]         io_writedata;
    logic               io_read;
    logic [7:0]         io_readdata;
    logic               io_waitrequest;

    // eSPI Mem Read/Write interface
    logic               mem_reset;
    logic [31:0]        mem_address;
    logic               mem_write;
    logic [31:0]        mem_writedata;
    logic [3:0]         mem_byteenable;
    logic               mem_read;
    logic [31:0]        mem_readdata = '0;
    logic               mem_waitrequest = 1'b0;

    // eSPI vUART Interface
    logic [7:0]         vuart_vw_irq0;
    logic [7:0]         vuart_vw_irq1;

    // Virtual Wire external inputs/outputs
    logic [255:0]       vw_irq;
    logic [255:0]       vw_plti;
    logic [255:0]       vw_plto;
    logic [511:0]       vw_gpi;
    logic [511:0]       vw_gpo;

    logic               reset;

    logic              peripheral_write;
    logic              peripheral_read;
    logic [31:0]       peripheral_writedata;
    logic [4:0]        peripheral_address;
    logic [31:0]       peripheral_readdata;
    logic              peripheral_readdatavalid;
    // peripheral AVMM interface is not used
    assign peripheral_write = '0;
    assign peripheral_read = '0;
    assign peripheral_writedata = '0;
    assign peripheral_address = '0;
    // VW IRQ not used
    assign vuart_vw_irq0 = '0;
    assign vuart_vw_irq1 = '0;
    logic [511:0] vgp_in;
    logic [511:0] vgp_out;

    assign rsmrst_n = reset_n;

    espi_platform_csr
      #(
        .TABLE_VERSION         ( TABLE_VERSION         )
        )
    espi_platform_csr
       (
       .clk                    ( clk                   ),
       .reset_n                ( reset_n               ),
       .espi_reset_n           ( spi_reset_n           ),
       // espi IO
       .io_reset               ( io_reset              ),
       .io_address             ( io_address            ),
       .io_write               ( io_write              ),
       .io_writedata           ( io_writedata          ),
       .io_read                ( io_read               ),
       .io_readdata            ( io_readdata           ),
       .io_waitrequest         ( io_waitrequest        ),
       // Programmed direction
       .plt_csr0               ( plt_csr0              ),
       .plt_csr1               ( plt_csr1              ),
       .plt_csr2               ( plt_csr2              ),
       .plt_csr3               ( plt_csr3              ),
       .plt_csr4               ( plt_csr4              ),
       .plt_csr5               ( plt_csr5              ),
       .plt_csr6               ( plt_csr6              ),
       .plt_csr7               ( plt_csr7              ),
       .plt_csr8               ( plt_csr8              ),
       .plt_csr9               ( plt_csr9              ),
       .plt_csra               ( plt_csra              ),
       .plt_csrb               ( plt_csrb              ),
       .plt_csrc               ( plt_csrc              ),
       .plt_csrd               ( plt_csrd              ),
       .plt_csre               ( plt_csre              ),
       .plt_csrf               ( plt_csrf              )
       );

    vgpio_avc_map vgpio_avc_map
      (
       .clk                              ( clk                              ),
       .reset_n                          ( reset_n                          ),
       // cpufpga vgpio fixed assignments
       .espi_reset_n                     ( spi_reset_n                      ),//vGPIO reset source
       // GPO from master to slave
       .PWRGD_AUX_PWRGD_CPU0_PLD         ( PWRGD_AUX_PWRGD_CPU0_PLD         ),
       .FM_UPI_INIT_DONE                 ( FM_UPI_INIT_DONE                 ),
       .RES_140_2                        ( RES_140_2                        ),
       .FM_ADR_MODE0                     ( FM_ADR_MODE0                     ),
       .FM_PERST_DELAY_SEL               ( FM_PERST_DELAY_SEL               ),
       // GPI from slave to master
       .FM_PASSWORD_CLEAR_N              ( FM_PASSWORD_CLEAR_N              ),
       .FM_BOARD_SKU_ID0                 ( FM_BOARD_SKU_ID0                 ),
       .FM_BOARD_SKU_ID1                 ( FM_BOARD_SKU_ID1                 ),
       .FM_BOARD_SKU_ID2                 ( FM_BOARD_SKU_ID2                 ),
       .FM_BOARD_SKU_ID3                 ( FM_BOARD_SKU_ID3                 ),
       .FM_BOARD_SKU_ID4                 ( FM_BOARD_SKU_ID4                 ),
       .FM_BOARD_SKU_ID5                 ( FM_BOARD_SKU_ID5                 ),
       .RES_147_2                        ( RES_147_2                        ),
       .RES_147_3                        ( RES_147_3                        ),
       .FM_BOARD_REV_ID0                 ( FM_BOARD_REV_ID0                 ),
       .FM_BOARD_REV_ID1                 ( FM_BOARD_REV_ID1                 ),
       .FM_BOARD_REV_ID2                 ( FM_BOARD_REV_ID2                 ),
       .FM_RST_PERST_BIT0                ( FM_RST_PERST_BIT0                ),
       .FM_RISER2_WIDTH                  ( FM_RISER2_WIDTH                  ),
       .FM_RISER2_MODE                   ( FM_RISER2_MODE                   ),
       .FM_RISER3_WIDTH                  ( FM_RISER3_WIDTH                  ),
       .FM_RISER3_MODE                   ( FM_RISER3_MODE                   ),
       .FM_CPU0_INTR_PRSNT_N             ( FM_CPU0_INTR_PRSNT_N             ),
       .FM_CPU1_INTR_PRSNT_N             ( FM_CPU1_INTR_PRSNT_N             ),
       .FM_CPU0_INTR_ID                  ( FM_CPU0_INTR_ID                  ),
       .FM_CPU1_INTR_ID                  ( FM_CPU1_INTR_ID                  ),
       .FM_PCIE_EV_BIF_EN                ( FM_PCIE_EV_BIF_EN                ),
       .H_CPU0_ERR0_LVC1_N               ( H_CPU0_ERR0_LVC1_N               ),
       .FM_SFFX4_EXPCARD_IO_B_0          ( FM_SFFX4_EXPCARD_IO_B_0          ),
       // Generic external IO
       .vgp_in                           ( vw_gpi                           ),
       .vgp_out                          ( vw_gpo                           )
       );

    espi_slave
      #( 
        .DEVICE_FAMILY              ( DEVICE_FAMILY              ),
        .IO_MODE_RANGE              ( IO_MODE_RANGE              ),
        .OPEN_DRAIN_ALERT_EN        ( OPEN_DRAIN_ALERT_EN        ),
        .MAX_FREQ_RANGE             ( MAX_FREQ_RANGE             ),
        .CHANNEL_SUPPORT            ( CHANNEL_SUPPORT            ),
        .MAX_PC_PAYLOAD_SIZE_RANGE  ( MAX_PC_PAYLOAD_SIZE_RANGE  ),
        .MAX_PC_READREQ_SIZE_RANGE  ( MAX_PC_READREQ_SIZE_RANGE  ),
        .MAX_OOB_PAYLOAD_SIZE_RANGE ( MAX_OOB_PAYLOAD_SIZE_RANGE ),
        .MAX_VW_COUNT_SUPPORTED     ( MAX_VW_COUNT_SUPPORTED     )
       )
    intel_espi_slave_0
      ( 
       .clk                       ( clk                      ),
       .reset_n                   ( reset_n                  ),
       // Peripheral AVMM
       .avmm_write                ( peripheral_write         ),
       .avmm_read                 ( peripheral_read          ),
       .avmm_writedata            ( peripheral_writedata     ),
       .avmm_address              ( peripheral_address       ),
       .avmm_readdata             ( peripheral_readdata      ),
       .avmm_readdatavalid        ( peripheral_readdatavalid ),
       // IO port
       .io_reset                  ( io_reset                 ),
       .io_address                ( io_address               ),
       .io_write                  ( io_write                 ),
       .io_writedata              ( io_writedata             ),
       .io_read                   ( io_read                  ),
       .io_readdata               ( io_readdata              ),
       .io_waitrequest            ( io_waitrequest           ),
       // Mem port
       .mem_reset                 ( mem_reset                ),
       .mem_address               ( mem_address              ),
       .mem_write                 ( mem_write                ),
       .mem_writedata             ( mem_writedata            ),
       .mem_byteenable            ( mem_byteenable            ),
       .mem_read                  ( mem_read                 ),
       .mem_readdata              ( mem_readdata             ),
       .mem_waitrequest           ( mem_waitrequest          ),
       // IRQ
       .irq                       (                          ),
       // Virtual wires
       .vw_irq                    ( vw_irq                   ),
       .vw_plti                   ( vw_plti                  ),
       .vw_plto                   ( vw_plto                  ),
       .vw_gpi                    ( vw_gpi                   ),
       .vw_gpo                    ( vw_gpo                   ),
       // misc
       .oob_rxfifo_avail          (                          ),
       .rsmrst_n                  ( rsmrst_n                 ),
       // espi IO
       .espi_clk                  ( spi_clk                  ),
       .espi_reset_n              ( spi_reset_n              ),
       .espi_cs_n                 ( spi_cs_n                 ),
       .espi_data_in              ( spi_data_in              ),
       .espi_data_out             ( spi_data_out             ),
       .espi_alert_n              ( spi_alert_n              ),
       // platform vw
       .slp_s3_n                  ( slp_s3_n                 ),
       .slp_s5_n                  ( slp_s5_n                 ),
       .slp_s4_n                  ( slp_s4_n                 ),
       .sus_stat_n                ( sus_stat_n               ),
       .pltrst_n                  ( pltrst_n                 ),
       .oob_rst_warn              ( oob_rst_warn             ),
       .host_rst_warn             ( host_rst_warn            ),
       .smiout_n                  ( smiout_n                 ),
       .nmiout_n                  ( nmiout_n                 ),
       .slave_boot_load_done      ( slave_boot_load_done     ),
       .slave_boot_load_status    ( slave_boot_load_status   ),
       .oob_rst_ack               ( oob_rst_ack              ),
       .wake_n                    ( wake_n                   ),
       .nmi_n                     ( nmi_n                    ),
       .pme_n                     ( pme_n                    ),
       .sci_n                     ( sci_n                    ),
       .smi_n                     ( smi_n                    ),
       .rcin_n                    ( rcin_n                   ),
       .host_rst_ack              ( host_rst_ack             ),
       .error_nonfatal            ( error_nonfatal           ),
       .error_fatal               ( error_fatal              ),
       // config csr: unused outputs
       .device_id_reg             ( device_id_reg            ),
       .general_config_reg        ( general_config_reg       ),
       .channel0_config_reg       ( channel0_config_reg      ),
       .channel1_config_reg       ( channel1_config_reg      ),
       .channel2_config_reg       ( channel2_config_reg      ),
       .channel3_config_reg       ( channel3_config_reg      )
       );

    always_comb begin
        vw_irq                            = 0;
        vw_irq[vuart_vw_irq0[6:0]]        = vuart_vw_irq0[7];
        vw_irq[vuart_vw_irq1[6:0]+8'd128] = vuart_vw_irq1[7];
    end

    always_comb begin
        vw_plti         = 0;
        vw_plti[0]      = 0;
        vw_plti[5*4+:8] = 0;

        sus_warn_n      = vw_plto[1*4+0];
        sus_pwrdn_ack   = vw_plto[1*4+1];
        slp_a_n         = vw_plto[1*4+3];
        slp_lan_n       = vw_plto[2*4+0];
        slp_wlan_n      = vw_plto[2*4+1];
        host_c10        = vw_plto[7*4+0];
    end

endmodule
